package ai.people.platform.archives.intimacy.handler;

import ai.people.core.nebula.util.NebulaQueryUtils;
import ai.people.netmon.framework.domain.graph.enums.GraphEdgeEnum;
import ai.people.netmon.framework.domain.graph.enums.GraphTagEnum;
import ai.people.netmon.framework.domain.key.account.vo.ExtendVO;
import ai.people.netmon.framework.exception.enums.GraphExceptionEnum;
import ai.people.netmon.framework.utils.AssertUtils;
import ai.people.netmon.utils.StringPool;
import com.vesoft.nebula.client.graph.data.ResultSet;
import com.vesoft.nebula.client.graph.data.ValueWrapper;
import com.vesoft.nebula.client.graph.exception.IOErrorException;
import com.vesoft.nebula.client.graph.net.SessionWrapper;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.UnsupportedEncodingException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author zhenglin
 * @date 2022/7/28
 */
public interface IntimacyHandleService {

    Logger log = LoggerFactory.getLogger(IntimacyHandleService.class);

    /**
     * 解析数据
     *
     * @param responseList 回复列表
     * @param ruleMapping
     * @param username
     * @param session
     * @return {@link List}<{@link ExtendVO}>
     */
    List<ExtendVO.Extend> analysis(List<?> responseList, Map<String, Integer> ruleMapping, String username, SessionWrapper session) throws IOErrorException, UnsupportedEncodingException;

    /**
     * 得到字段的权重
     *
     * @param field       场
     * @param ruleMapping 规则映射
     * @return int
     */
    default int getFieldWeight(String field, Map<String, Integer> ruleMapping) {
        return ruleMapping.getOrDefault(field, 0);
    }


    /**
     * 获取同板块映射
     *
     * @param session   会话
     * @param vidList 回复列表
     * @param username  用户名
     * @return {@link Map}<{@link String}, {@link Integer}>
     * @throws IOErrorException             ioerror异常那么
     * @throws UnsupportedEncodingException 不支持编码异常
     */
    default Map<String, Integer> getSameSectionMapping(SessionWrapper session, Set<String> vidList, String username) throws IOErrorException, UnsupportedEncodingException {
        return getSameMapping(session, vidList, username, GraphEdgeEnum.SAME_SECTION.edgeName, GraphTagEnum.REDDIT_SECTION.tagName, GraphTagEnum.REDDIT.vidPrefix);
    }

    /**
     * 获取reddit同群映射
     *
     * @param session   会话
     * @param vidList 回复列表
     * @param username  用户名
     * @return {@link Map}<{@link String}, {@link Integer}>
     * @throws IOErrorException             ioerror异常那么
     * @throws UnsupportedEncodingException 不支持编码异常
     */
    default Map<String, Integer> getSameTelegramGroupMapping(SessionWrapper session, Set<String> vidList, String username) throws IOErrorException, UnsupportedEncodingException {
        return getSameMapping(session, vidList, username, GraphEdgeEnum.SAME_GROUP.edgeName, GraphTagEnum.TELEGRAM_GROUP.tagName, GraphTagEnum.TELEGRAM.vidPrefix);
    }


    default Map<String, Integer> getSameMapping(SessionWrapper session, Set<String> vidList, String username, String edgeName, String sameTagName, String vidTagName) throws IOErrorException, UnsupportedEncodingException {
        String vid = NebulaQueryUtils.buildVid(vidTagName, username);
        List<String> sameSection = getSameSection(session, vid, edgeName, sameTagName);
        return checkInSameSection(session, edgeName, sameSection, vidList);
    }

    default Map<String, Integer> checkInSameSection(SessionWrapper session, String edge, Collection<String> sectionVidList, Collection<String> replayVidList) throws IOErrorException, UnsupportedEncodingException {
        String sectionVidListStr = "\"" + StringUtils.join(sectionVidList, "\",\"") + "\"";
        String replayVidListStr = "\"" + StringUtils.join(replayVidList, "\",\"") + "\"";

        String gql = "MATCH (v1)-[e:" + edge + "]-(v2) where id(v1) in [" + sectionVidListStr + "] and id(v2) in [" + replayVidListStr + "] RETURN id(v1),id(v2) ";
        log.info("nGQL: {}", gql);
        ResultSet resultSet = session.execute(gql);
        int rowsSize = resultSet.rowsSize();

        Map<String, List<String>> vidMap = new HashMap<>();

        for (int i = 0; i < rowsSize; i++) {
            ResultSet.Record valueWrappers = resultSet.rowValues(i);
            ValueWrapper sectionVal = valueWrappers.get(0);
            ValueWrapper verVal = valueWrappers.get(1);

            String secVid = sectionVal.asString();
            String verVid = verVal.asString();

            if (vidMap.containsKey(verVid)) {
                vidMap.get(verVid).add(secVid);
            } else {
                List<String> list = new ArrayList<>();
                list.add(secVid);
                vidMap.put(verVid, list);
            }
        }
        return vidMap.entrySet().stream().collect(Collectors.toMap(x -> x.getKey().split(StringPool.COLON)[1], x -> x.getValue().size()));
    }

    /**
     * 得到同群的ID
     *
     * @param vid     从视频
     * @param session 会话
     * @return {@link List}<{@link String}>
     * @throws IOErrorException             ioerror异常那么
     * @throws UnsupportedEncodingException 不支持编码异常
     */
    default List<String> getSameSection(SessionWrapper session, String vid, String edge, String tagName) throws IOErrorException, UnsupportedEncodingException {
        List<String> ids = new ArrayList<>();
        String gql = "match (v1)-[e:" + edge + "]-(v2:" + tagName + ") where id(v1) == \"" + vid + "\" return DISTINCT id(v2) as id";
        log.info("nGQL: {}", gql);
        ResultSet resultSet = session.execute(gql);
        boolean b = NebulaQueryUtils.checkErr(resultSet);
        AssertUtils.isTrue(b, GraphExceptionEnum.OPT_ERR);

        int rowsSize = resultSet.rowsSize();
        for (int i = 0; i < rowsSize; i++) {
            ResultSet.Record valueWrappers = resultSet.rowValues(i);
            ValueWrapper idVal = valueWrappers.get(0);
            ids.add(idVal.asString());
        }

        return ids;
    }
}
